package com.yhy.wxzn.wcs.device.scanner;

import com.yhy.wxzn.common.utils.WcsUtils;
import com.yhy.wxzn.wcs.device.scanner.bean.IpAddress;
import com.yhy.wxzn.wcs.device.scanner.handler.BarcodeScannerClientHandler;
import com.yhy.wxzn.wcs.entity.DeviceNetworkInfo;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;


/**
 * 1.发送"T"开始拍照，持续时间5秒，超时返回空
 * 2."\u0002\u0018\r\n"为空
 * 3."\u0002 code \r\n" 为有值
 * 4.断电后TCP不会重新连接
 */
@Slf4j
public class BarcodeScannerClient extends Thread{

    public static final Map<String,BarcodeScannerClient> deviceNameToBarcodeScannerClient = new HashMap<>();

    public static final String sendMessage = "T";
    /**
     * STX 是一个控制字符，用于指示文本的起始位置。在通信协议中，可以使用 STX 来标识数据包的开始。
     */
    public static final char STX = '\u0002';
    /**
     * CAN 是一个控制字符，通常用于取消当前操作或传输。在通信协议中，CAN 可以用来中止正在进行的数据传输。
     */
    public static final char CAN = '\u0018';




    private IpAddress ipAddress;


    private ChannelFuture channelFuture;


    private BarcodeScannerClientHandler barcodeScannerClientHandler;

    private NioEventLoopGroup group;

    public BarcodeScannerClient(DeviceNetworkInfo deviceNetworkInfo) {
        super("扫码器客户端线程[ip:"+ deviceNetworkInfo.getIp()+",port:"+ deviceNetworkInfo.getPort()+",name:"+ deviceNetworkInfo.getDeviceName()+"]");

        this.ipAddress = new IpAddress(deviceNetworkInfo.getIp(),deviceNetworkInfo.getPort());

        deviceNameToBarcodeScannerClient.put(deviceNetworkInfo.getDeviceName(),this);
    }

    @SneakyThrows
    @Override
    public void run() {
        while (true){
            try {
                connect();
            }catch (Exception e){
                log.error(e.getMessage(),e);
            }
            WcsUtils.sleep(60000);
        }
    }

    private void connect() throws InterruptedException {
        if (isConnected())
            return;

        group = new NioEventLoopGroup();
        barcodeScannerClientHandler = new BarcodeScannerClientHandler();

        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(barcodeScannerClientHandler);
                        //ch.pipeline().addLast(new LoggingHandler());
                    }
                })
                .option(ChannelOption.SO_KEEPALIVE, true);

        channelFuture = bootstrap.connect(ipAddress.getIp(), ipAddress.getPort());
        channelFuture.awaitUninterruptibly(10000);
        if (!channelFuture.isSuccess()) {
            log.info("连接[" + ipAddress.toString() + "]超时！");
            return;
        }

        channelFuture.channel().closeFuture().addListener(cfl -> { close(); });
    }


    private boolean isConnected(){
        return barcodeScannerClientHandler != null && barcodeScannerClientHandler.isConnected();
    }
    public void close() {
        //关闭客户端线程组
        if (group != null) {
            group.shutdownGracefully();
        }
        log.info(ipAddress.toString() + "关闭连接，释放对象！");
    }


    /**
     * 触发扫码器一次扫码动作，并返回扫码结果
     * @return
     */
    public synchronized String getBarCode(){
        if (!isConnected()){
            log.error("扫码器连接中...,{}",ipAddress.toString());
            WcsUtils.sleep(60000);
            return "";
        }
        channelFuture.channel().writeAndFlush(Unpooled.wrappedBuffer(sendMessage.getBytes()));


        int t = 0;
        while (!barcodeScannerClientHandler.isHaveMessage() &&  t++ < 30) WcsUtils.sleep(100);


        if (t >= 30){
            //log.error("读码器未扫到条码！,ip:{},port:{}",ipAddress.getIp(),ipAddress.getPort());
            return "";
        }

        barcodeScannerClientHandler.setHaveMessage(false);
        return barcodeScannerClientHandler.getBarCode();
    }

//    public static void main(String[] args) throws InterruptedException {
//        String serverIp = "192.168.101.233";
//        int serverPort = 10000;
//        IpAddress ipAddress = new IpAddress(serverIp, serverPort);
//        BarcodeScannerClient client = new BarcodeScannerClient(ipAddress);
//        client.start();
//        while (true){
//
//            String barCode = client.getBarCode();
//            log.info(barCode);
//            WcsUtils.sleep(6000);
//        }
//
//    }
}
